#pragma once

#include<iostream>
#include<cstdio>
#include<string>
#include<cstdlib>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include<unistd.h>
#include<cstring>

const int size = 4096;
const int rd = 1234;
const std::string path = ".";



#define ERR_EXIT(m) \
do \
{ \
    perror(m); \
    exit(EXIT_FAILURE); \
} while(0)

#define GETKEY ftok(path.c_str(),rd)


class Shm
{
public:
    Shm()
    {

    }

    ~Shm()
    {

    }

    void Create()
    {
        int id =shmget(GETKEY,size,IPC_CREAT | IPC_EXCL | 0666);
        if(-1 == id)
        {
            ERR_EXIT("shmget create fail");
        }
        _shmid = id;
    }

    void Get()
    {
        int id = shmget(GETKEY,size,IPC_CREAT);
        if(-1 == id)
        {
            ERR_EXIT("shmget get fail");
        }
        _shmid = id;
    }

    void Attach()
    {
        void* start = shmat(_shmid,nullptr,0);
        if(start == (void*)-1)
        {
            ERR_EXIT("attach fail");
        }
        _start = start;
    }

    void Detach()
    {
        int n =shmdt(_start);
        if(n == -1)
        {
            ERR_EXIT("detach fail");
        }
        else if(n == 0)
        {
            std::cout<< "取消关联成功"<<std::endl;
        }
    }

    

    void Delete()
    {
        int n = shmctl(_shmid,IPC_RMID,nullptr);
        if(-1 == n)
        {
            ERR_EXIT("delete fail");
        }
        else 
        {
            std::cout<<"delete success" << std::endl;
        }
    }

    void* GetAdd()
    {   
        return _start;
    }

private:
    int _shmid;
    void* _start;
};
